﻿/*
 * @Autor: PK
 * @Date: 2021-03-17 08:44:17
 * @Description: 次级服务台调用链，实现了Chain
 */

using System;
using System.Collections.Generic;
using ShkSimulation.core.dao.statistic;
using ShkSimulation.core.exceptions;
using ShkSimulation.core.template.customer;

namespace ShkSimulation.core.template.agency {

    [Flags]
    public enum InternalAgencyServeTime {
        None = 0x1,
        BeforeArrive = 0x2,
        BeforeServe = 0x4,
        BeforeDepart = 0x8,
    }

    public class InternalAgencyChain: DataReporter {

        protected internal List<InternalAgency> AllInternalAgencies { get; private set; } = new List<InternalAgency>();

        protected internal List<InternalAgency> BeforeArriveAgencies { get; } = new List<InternalAgency>();
        protected internal List<InternalAgency> BeforeServeAgencies { get; } = new List<InternalAgency>();
        protected internal List<InternalAgency> BeforeDepartAgencies { get; } = new List<InternalAgency>();
        
        protected internal Agency Agency { get; set; }
        
        protected internal InternalAgencyChain(Agency agency, List<InternalAgency> internalAgencies = null) {
            if (agency == null) {
                throw new ErrorParamException("父级服务机构为空");
            }
            Agency = agency;
            if (internalAgencies == null || internalAgencies.Count == 0) {
                AllInternalAgencies = new List<InternalAgency>();
                return;
            }
            foreach (var internalAgency in internalAgencies) {
                AddAgency(internalAgency);
            }
        }
        
        protected internal void AddAgency(InternalAgency agency) {
            if(agency == null) {
                return;
            }
            if ((agency.ServeTime & InternalAgencyServeTime.BeforeArrive) != 0) {
                BeforeArriveAgencies.Add(agency);
            }
            if ((agency.ServeTime & InternalAgencyServeTime.BeforeServe) != 0) {
                BeforeServeAgencies.Add(agency);
            }
            if ((agency.ServeTime & InternalAgencyServeTime.BeforeDepart) != 0) {
                BeforeDepartAgencies.Add(agency);
            }
            AllInternalAgencies.Add(agency);
        }
        
        protected internal void RemoveAgency(InternalAgency agency){
            if(agency == null){
                return;
            }
            AllInternalAgencies.Remove(agency);
            if ((agency.ServeTime & InternalAgencyServeTime.BeforeArrive) != 0) {
                BeforeArriveAgencies.Remove(agency);
            }
            if ((agency.ServeTime & InternalAgencyServeTime.BeforeServe) != 0) {
                BeforeServeAgencies.Remove(agency);
            }
            if ((agency.ServeTime & InternalAgencyServeTime.BeforeDepart) != 0) {
                BeforeDepartAgencies.Remove(agency);
            }
        }
        
        protected internal void ChainArrive(Customer customer) {
            if(BeforeArriveAgencies.Count == 0){
                return;
            }
            int index = customer.BeforeArriveInternalAgencyIndex;
            if (index == BeforeArriveAgencies.Count) {
                Agency.Arrive(customer);
                return;
            }
            customer.BeforeArriveInternalAgencyIndex = index + 1;
            this.BeforeArriveAgencies[index].Arrive(customer);
        }
        
        protected internal void ChainDepart(Customer customer) {
            if(BeforeDepartAgencies.Count == 0){
                return;
            }
            int index = customer.BeforeDepartInternalAgencyIndex;
            if (index == BeforeDepartAgencies.Count) {
                Agency.Depart(customer);
                return;
            }
            customer.BeforeDepartInternalAgencyIndex = index + 1;
            this.BeforeDepartAgencies[index].Depart(customer);
        }

        protected internal void ChainServe(Customer customer){
            if(BeforeServeAgencies.Count == 0){
                return;
            }
            int index = customer.BeforeServeInternalAgencyIndex;
            if (index == BeforeServeAgencies.Count) {
                Agency.Serve(customer);
                return;
            }
            customer.BeforeServeInternalAgencyIndex = index + 1;
            this.BeforeServeAgencies[index].Serve(customer);
        }
        
        #region 状态
        
        public int Count => AllInternalAgencies == null ? 0 : AllInternalAgencies.Count;
        
        #endregion

        public string Uniquekey => $"{Agency.Uniquekey}#internalChain";

        public event Action<DataReporter> ReportToCollection;

        public DataReportInfo GetReportInfo() {
            DataReportInfo dataReportInfo = DataReportInfo.Empty();
            foreach (var allInternalAgency in AllInternalAgencies) {
                if (allInternalAgency is DataReporter dataReporter) {
                   dataReportInfo.Merge(dataReporter.GetReportInfo());
                }
            }
            return dataReportInfo;
        }

    }
}
